package com.lonely.order.support.synchronizer.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.order.domain.dto.api.QueryProduceOrderInfoByIdReqDTO;
import com.lonely.order.domain.dto.api.QueryProduceOrderInfoByIdResDTO;
import com.lonely.order.domain.entity.SysOrder;
import com.lonely.order.domain.entity.SysOrderSecondProcess;
import com.lonely.order.domain.entity.SysSheinOpenApiSecret;
import com.lonely.order.enums.OrderEnum;
import com.lonely.order.mapper.*;
import com.lonely.order.service.*;
import com.lonely.order.support.synchronizer.SynchronizerOrderContext;
import com.lonely.order.threadlocals.OrderSynchronizedThreadLocal;
import com.lonely.common.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/7/31 15:30
 * @description: 同步订单服务
 */
@Service
@Slf4j
public class SynchronizerOrderService {

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IOrderPartService orderPartService;

    @Autowired
    private IOrderPartMaterialService orderPartMaterialService;

    @Autowired
    private IOrderSecondProcessService orderSecondProcessService;

    @Autowired
    private IOrderProcessService orderProcessService;

    @Autowired
    private IOrderProcessItemService orderProcessItemService;

    @Autowired
    private IMesApiService mesApiService;

    @Autowired
    private SynchronizerOrderPartService synchronizerOrderPartService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 同步订单数据
     *
     * @param openApiSecret
     * @param orderIdsByDate
     */
    public void synchronizerOrder(SysSheinOpenApiSecret openApiSecret, List<Long> orderIdsByDate) {

        // 获取有效的订单数据
        List<QueryProduceOrderInfoByIdResDTO> orderInfosByDate = getOrderInfosByDate(openApiSecret, orderIdsByDate);
        if (CollUtil.isEmpty(orderInfosByDate)) {
            return;
        }

        // 入库
        for (QueryProduceOrderInfoByIdResDTO orderInfoByIdResDTO : orderInfosByDate) {

            // 加锁, 防止重新创建订单
            String lockKey = String.format("synchronizer:orders:%s", orderInfoByIdResDTO.getProduceOrderId());
            RLock lock = redissonClient.getLock(lockKey);
            boolean isLocked = false;

            // 创建上下文
            SynchronizerOrderContext synchronizerOrderContext = new SynchronizerOrderContext();
            synchronizerOrderContext.setOrderInfoById(orderInfoByIdResDTO);
            synchronizerOrderContext.setOpenApiSecret(openApiSecret);

            try {
                // 尝试获取锁，参数分别是等待时间、锁自动释放时间、时间单位
                // 不等待，直接尝试获取锁，获取成功则执行逻辑
                isLocked = lock.tryLock(0, 10, TimeUnit.SECONDS);
                if (!isLocked) {
                    // 执行需要加锁保护的操作
                    log.debug("同步订单号：{}数据未获取到锁,退出此次同步", orderInfoByIdResDTO.getProduceOrderId());
                    continue;
                }

                // 判断该订单号是否已存在
                SysOrder oldOrder = this.orderService.getOne(new LambdaQueryWrapper<SysOrder>()
                        .eq(SysOrder::getProduceOrderId, orderInfoByIdResDTO.getProduceOrderId())
                );
                if (oldOrder != null) {
                    // 订单数据已存在，则同步修改订单状态
                    oldOrder.setOriginalOrderStatus(orderInfoByIdResDTO.getStatus());

                    // 如果订单状态为已作废，则修改本地订单状态
                    if(StrUtil.equals(orderInfoByIdResDTO.getStatus(),"已作废") || StrUtil.equals(orderInfoByIdResDTO.getStatus(),"待作废")){
                        oldOrder.setStatus(OrderEnum.OrderStatus.REPEALED.getDesc());
                        oldOrder.setStatusInt(OrderEnum.OrderStatus.REPEALED.getStatus());
                    }

                    this.orderService.updateById(oldOrder);
                    continue;
                }

                // 不存在，则开始处理
                // 添加订单
                SysOrder sysOrder = saveOrderInfo(synchronizerOrderContext);
                synchronizerOrderContext.setNewOrder(sysOrder);
                synchronizerOrderContext.setOrderId(sysOrder.getId());
                synchronizerOrderContext.setProduceOrderId(sysOrder.getProduceOrderId());

                // 添加订单物料数据
                this.synchronizerOrderPartService.synchronizerOrderPart(synchronizerOrderContext);

            } catch (Exception e) {
                log.error("同步订单号：{}数据失败", orderInfoByIdResDTO.getProduceOrderId(), e);
//                FileUtil.appendUtf8String(String.format("订单号：%s,异常原因：%s \n\r", orderInfoByIdResDTO.getProduceOrderId(), ExceptionUtils.getStackTrace(e)), "C:\\data\\synchronizedOrderError.txt");
                if (synchronizerOrderContext.getOrderId() != null) {
                    // 回滚数据
                    rollBackData(synchronizerOrderContext.getOrderId());
                }
            } finally {
                if (isLocked) {
                    lock.unlock();
                }
            }
        }


    }

    /**
     * 回滚数据
     *
     * @param orderId
     */
    private void rollBackData(Long orderId) {

        // 删除新增的订单
        ((SysOrderMapper) this.orderService.getBaseMapper()).physicalDeletionById(orderId);

        // 删除该部件的信息
        ((SysOrderPartMapper) this.orderPartService.getBaseMapper()).physicalDeletionByOrderId(orderId);

        // 删除该部件对应的物料信息
        ((SysOrderPartMaterialMapper) this.orderPartMaterialService.getBaseMapper()).physicalDeletionByOrderId(orderId);

        // 删除该订单对应的二次工艺信息
        ((SysOrderSecondProcessMapper) this.orderSecondProcessService.getBaseMapper()).physicalDeletionByOrderId(orderId);

        // 删除该订单对应的工序信息
        List<Long> needDeleteOrderProcessIds = this.orderSecondProcessService.list(new LambdaQueryWrapper<SysOrderSecondProcess>()
                .eq(SysOrderSecondProcess::getOrderId, orderId)
        ).stream().map(BaseEntity::getId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(needDeleteOrderProcessIds)) {
            ((SysOrderProcessMapper) this.orderProcessService.getBaseMapper()).physicalDeletionByOrderId(orderId);

            // 删除该订单对应的工序明细信息
            ((SysOrderProcessItemMapper) this.orderProcessItemService.getBaseMapper()).physicalDeletionByOrderProcessIds(needDeleteOrderProcessIds);
        }
    }


    /**
     * 保存订单数据
     *
     * @param synchronizerOrderContext
     */
    private SysOrder saveOrderInfo(SynchronizerOrderContext synchronizerOrderContext) {
        QueryProduceOrderInfoByIdResDTO orderInfoByIdResDTO = synchronizerOrderContext.getOrderInfoById();
        SysSheinOpenApiSecret openApiSecret = synchronizerOrderContext.getOpenApiSecret();

        SysOrder sysOrder = new SysOrder();
        BeanUtils.copyProperties(orderInfoByIdResDTO, sysOrder);
        sysOrder.setProduceOrderId(Convert.toLong(orderInfoByIdResDTO.getProduceOrderId()));

        // 颜色
        sysOrder.setColor(orderInfoByIdResDTO.getColors());

        // 是否首单
        sysOrder.setIsFirst(Objects.equals(orderInfoByIdResDTO.getIsFirst(), "首") ? OrderEnum.IsFirstOrder.FIRST_ORDER.getType() : OrderEnum.IsFirstOrder.RETURN_ORDER.getType());

        // 设置优先级
        sysOrder.setIsUrgent(Objects.equals("普通", orderInfoByIdResDTO.getIsUrgent()) ? 0 : 1);

        // 设置工厂id
        sysOrder.setFactoryId(openApiSecret.getFactoryId());

        // 设置工厂权限
        sysOrder.setFactoryPermission(JsonUtil.toJsonString(Lists.newArrayList(openApiSecret.getFactoryId())));

        // 设置客户id
        sysOrder.setCustomerId(openApiSecret.getCustomerId());

        // 如果订单状态为已作废，则修改本地订单状态
        if(StrUtil.equals(orderInfoByIdResDTO.getStatus(),"已作废") || StrUtil.equals(orderInfoByIdResDTO.getStatus(),"待作废")){
            sysOrder.setStatus(OrderEnum.OrderStatus.REPEALED.getDesc());
            sysOrder.setStatusInt(OrderEnum.OrderStatus.REPEALED.getStatus());
        }else {
            // 设置订单为初始状态 待采购
            sysOrder.setStatus(OrderEnum.OrderStatus.TO_BE_PURCHASED.getDesc());
            sysOrder.setStatusInt(OrderEnum.OrderStatus.TO_BE_PURCHASED.getStatus());
        }

        // 设置原始订单类型
        sysOrder.setOriginalOrderStatus(orderInfoByIdResDTO.getStatus());
//        sysOrder.setOriginalOrderStatusInt(OrderEnum.OrderStatus.getStatusByStatusName(orderInfoByIdResDTO.getStatus()));

        // 设置订单类型
        OrderEnum.OrderType orderType = OrderEnum.OrderType.getInstanceByDesc(orderInfoByIdResDTO.getOrderType());
        if (orderType != null) {
            sysOrder.setOrderTypeInt(orderType.getType());
        }

        // 设置备货类型
        OrderEnum.OrderStockType orderStockType = OrderEnum.OrderStockType.getInstanceByDesc(orderInfoByIdResDTO.getStockType());
        if (orderStockType != null) {
            sysOrder.setStockTypeInt(orderStockType.getType());
        }

        sysOrder.setOrderInfo(JsonUtil.toJsonString(orderInfoByIdResDTO.getOrderInfo()));

        // 订单价格
        sysOrder.setOrderPrice(NumberUtil.toBigDecimal(orderInfoByIdResDTO.getOrderPrice()));

        sysOrder.setSecondProcess(JsonUtil.toJsonString(orderInfoByIdResDTO.getSecondProcess()));
        sysOrder.setCutBedInfo(JsonUtil.toJsonString(orderInfoByIdResDTO.getCutBedInfo()));
        sysOrder.setCreateBy(OrderSynchronizedThreadLocal.getCreateBy());
        sysOrder.setUpdateBy(OrderSynchronizedThreadLocal.getCreateBy());
        if (OrderSynchronizedThreadLocal.isTaskTrigger()) {
            // 定时任务触发，则使用默认用户
            sysOrder.setRemark("定时任务触发同步");
        }
        this.orderService.save(sysOrder);
        return sysOrder;
    }

    /**
     * 获取指定日期的订单集合
     *
     * @param sheinOpenApiSecret
     * @param orderIdsByDate
     * @return
     */
    private List<QueryProduceOrderInfoByIdResDTO> getOrderInfosByDate(SysSheinOpenApiSecret sheinOpenApiSecret, List<Long> orderIdsByDate) {
        if (CollUtil.isEmpty(orderIdsByDate)) {
            return new ArrayList<>();
        }

//        // 提取有效订单号
//        List<SysOrder> existsOrders = this.orderService.list(new LambdaQueryWrapper<SysOrder>()
//                .in(SysOrder::getProduceOrderId, orderIdsByDate));
//        List<Long> currentExistsOrderIds = existsOrders.stream().map(SysOrder::getProduceOrderId).distinct().collect(Collectors.toList());
//
//        // 剔除已存在的订单号
//        List<Integer> effectiveOrderIds = orderIdsByDate.stream().filter(x -> !currentExistsOrderIds.contains(x)).map(Convert::toInt).collect(Collectors.toList());
//
//        if (CollUtil.isEmpty(effectiveOrderIds)) {
//            return new ArrayList<>();
//        }

        // 调接口，分别获取对应的订单信息
        List<QueryProduceOrderInfoByIdResDTO> orderInfos = new ArrayList<>();
        for (Long effectiveOrderId : orderIdsByDate) {
            try {
                QueryProduceOrderInfoByIdReqDTO reqDTO = new QueryProduceOrderInfoByIdReqDTO();
                reqDTO.setProduceOrderId(effectiveOrderId);

                int count = 0;
                QueryProduceOrderInfoByIdResDTO produceOrderInfoByIdResDTO ;
                do {
                    try {
                        produceOrderInfoByIdResDTO = mesApiService.queryProduceOrderInfoById(sheinOpenApiSecret, reqDTO);
                    } catch (Exception e) {
                        if (count < 3) {
                            if (e.getMessage().contains("限流")) {
                                // 重试
                                count++;
                                ThreadUtil.sleep(500);
                                continue;
                            }
                        }
                        throw e;
                    }
                    break;
                } while (true);

                if (produceOrderInfoByIdResDTO != null) {
                    orderInfos.add(produceOrderInfoByIdResDTO);
                }
            } catch (Exception e) {
                log.error("根据订单号：{}获取订单数据接口失败：{}", effectiveOrderId, e.getMessage());
//                FileUtil.appendUtf8String(String.format("订单号：%s 获取订单详情接口,异常原因：%s \n\r", effectiveOrderId, e.getMessage()), "C:\\data\\synchronizedOrderError.txt");
            }
        }
        return orderInfos;
    }

}
